#ifndef STX_PLATFORM_POSIX_THREAD_THREAD_KEY_HPP
#define STX_PLATFORM_POSIX_THREAD_THREAD_KEY_HPP

#include <stx/platform/posix/thread/common.hpp>

namespace stx {

namespace posix {

class thread_key
{
public:
    
    typedef thread_key this_type;
    
    thread_key(void (*destructor)(void*) = NULL)
    {
        int ret = pthread_key_create(&handle_, destructor);
        if (ret) {
            STX_THROW_SYSTEM_ERROR_VAL(ret, "pthread_key_create");
        }
    }
    
    thread_key(const thread_key& key)
    {
        handle_ = key.handle();
    }
    
    ~thread_key()
    {
        int ret = pthread_key_delete(handle_);
        if (ret) {
            STX_DESTRUCTOR_SYSTEM_ERROR_VAL(ret, "pthread_key_delete");
        }
    }
    
    void* get_specific()
    {
        return pthread_getspecific(handle_);
    }
    
    void set_specific(const void* value)
    {
        int ret = pthread_setspecific(handle_, value);
        if (ret) {
            STX_THROW_SYSTEM_ERROR_VAL(ret, "pthread_setspecific");
        }
    }
    
    typedef pthread_key_t handle_type;
    
    handle_type handle()
    {
        return handle_;
    }
    
    const handle_type handle() const
    {
        return handle_;
    }
    
private:
    
    handle_type handle_;
};

} // namespace posix

} // namespace stx

#endif // STX_PLATFORM_POSIX_THREAD_THREAD_KEY_HPP
